package com.wuwei.elearning.test;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wuwei.elearning.exception.ElearningMysqlException;
import com.wuwei.elearning.question.domain.Question;
import com.wuwei.elearning.question.domain.SpecialCare;
import com.wuwei.elearning.question.domain.Subject;
import com.wuwei.elearning.question.mapper.*;
import org.apache.poi.xwpf.usermodel.*;
import org.jetbrains.annotations.NotNull;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class SetDa42 {

    private String engine;

    private String ata22Type;

    public void setQuestions(String engine, String ata22Type,Integer type)  {
        this.engine = engine;
        this.ata22Type = ata22Type;
        /*
        1.先拿到Da42考卷各子章节需要出多少道题，放到一个arrayList中
        2.再拿到Da42所有的考题
        3.根据Da42各子章节需求出题的数量出题，出完再放到一个考卷arrayList中
        4.将考卷arrayList中的题目写到一个docx文件中
        5.将写好的docx文件地址返回给controller层，由controller层返回给前端
         */
        setQuestionZhCn(engine, ata22Type);
    }

    @Resource
    private QuestionSettingForDa42SupMapper questionSettingForDa42SupMapper;

    @Resource
    private QuestionMapper questionMapper;


    @Resource
    private QuestionSettingForDa42Mapper questionSettingForDa42Mapper;
    @Autowired
    private SubjectMapper subjectMapper;

    /**
     * 纯中文的题目
     * @param engine
     * @param ata22Type
     */
    private void setQuestionZhCn(String engine, String ata22Type) {
//        List<Question> questions = getQuestions(engine, ata22Type);
        List<Question> questions = getQuestionsWithSpecialCares(engine, ata22Type);
        this.setToWord(questions);
    }

    @Resource
    private SpecialCareMapper specialCareMapper;

    @NotNull
    private static List<Subject> filterSubjects(String engine, String ata22Type, List<Subject> subjects) {
        if (engine.equals("E4")) {
            subjects = subjects.stream().filter(s -> !s.getName().contains("TAE")).collect(Collectors.toList());
        } else if (engine.equals("TAE")) {
            subjects = subjects.stream().filter(s -> !s.getName().contains("E4")).collect(Collectors.toList());
        } else {
            throw new ElearningMysqlException(20001,"发动机类型必须是E4或TAE！");
        }

        if (ata22Type.equals("GFC700")) {
            subjects = subjects.stream().filter(s -> !s.getName().contains("KAP140")).collect(Collectors.toList());
        } else if (ata22Type.equals("KAP140")) {
            subjects = subjects.stream().filter(s -> !s.getName().contains("GFC700")).collect(Collectors.toList());
        } else {
            throw new ElearningMysqlException(20001,"航电系统类型必须是KAP140或GFC700！");
        }
        return subjects;
    }

    /**
     * 获取带有特别关注点的机型题目
     * 1 根据科目id随机获取所有机型题目，某一个科目需要获取的题目数量为该科目的时长除以60的向上取整
     * 2 优先获取特别关注点的题目
     * 3 某一科目的特别关注点的数量不能超过该科目应该获取的总的题目数量
     * 4 特别关注点的题目获取完了以后，如果还要获取题目，则获取普通题目
     * @return
     */
    private List<Question> getQuestionsWithSpecialCares(String engine, String ata22Type){
        List<Subject> subjects = subjectMapper.getLeafsById(7L);
        subjects = filterSubjects(engine, ata22Type, subjects);
        List<Question> questions = new ArrayList<>();
        // question表中的subjectId就是subject的主键，因此可以根据subjects的id去question表中查数据
        for (Subject subject : subjects) {
            Long id = subject.getId();
            Integer duration = subject.getDuration();
            Integer count = (int) Math.ceil((double) duration /60);
            //先去查询该subject有几个特别关注点，一个特别关注点只出一道题
            List<SpecialCare> specialCares = specialCareMapper.selectList(new LambdaQueryWrapper<SpecialCare>().eq(SpecialCare::getSubjectId, subject.getId()));
            ArrayList<Long> qid = new ArrayList<>();
            if (!specialCares.isEmpty()) {
                if (specialCares.size()>count) {
                    throw new ElearningMysqlException(30055, "题目生成失败，id为" + id + "的题目特别关注点数量大于题目数量！");
                }
                List<Question> specialQuestions = new ArrayList<>();
                for (SpecialCare specialCare : specialCares) {
                    Integer specialCareId = specialCare.getId();
                    //根据特别关注点id和subjectId去question表中查数据，这里随机查找一条数据
                    List<Question> q = questionMapper.randomSelectBySpecialCareId(id,specialCareId, 1);
                    specialQuestions.addAll(q);
                }
                qid = specialQuestions.stream().map(Question::getId).collect(Collectors.toCollection(ArrayList::new));
                questions.addAll(specialQuestions);
            }
            //特别关注点的题目查找完了以后，再去查找剩余的题目,这里再去查找的时候不能和之前的题目重复
            List<Question> questionList = new ArrayList<>();
            if (qid.isEmpty()) {
                questionList = questionMapper.randomSelect(id,count-specialCares.size());
            } else {
                questionList = questionMapper.randomSelectWithoutInQid(id,count-specialCares.size(),qid);
            }

            if (questionList.size()!=count-specialCares.size()) {
                throw new ElearningMysqlException(30055, "题目生成失败，id为" + id + "题库内题目数量不足以支撑生成题库！");
            }
            questions.addAll(questionList);
        }
        return questions;
    }

    /**
     * 取消表格的边框
     * @param table
     */
    private void setTableBorders(XWPFTable table) {
        // 设置表格的边框为0，即隐藏所有边框
        CTTblBorders tblBorders = table.getCTTbl().getTblPr().addNewTblBorders();
        tblBorders.addNewBottom().setVal(STBorder.NONE);
        tblBorders.addNewTop().setVal(STBorder.NONE);
        tblBorders.addNewLeft().setVal(STBorder.NONE);
        tblBorders.addNewRight().setVal(STBorder.NONE);
        tblBorders.addNewInsideH().setVal(STBorder.NONE);
        tblBorders.addNewInsideV().setVal(STBorder.NONE);
    }

    /**
     * 将questions写入word
     * @param setQuestionList
     */
    private void setToWord(List<Question> setQuestionList) {
        String templatePath = "template.docx";
        String wordPath = "word.docx";
        try {
            File file = new File(templatePath);
            if (!file.exists()) {
                throw new ElearningMysqlException(30011, "请检查模板文件是否存在！");
            }
            InputStream is = Files.newInputStream(Paths.get(templatePath));
            XWPFDocument document = new XWPFDocument(is);

            //设置考卷信息
            List<XWPFParagraph> paragraphs = document.getParagraphs();
            XWPFParagraph paragraph = paragraphs.get(1);
            paragraph.getRuns().get(0).setBold(true);

            XWPFTable table = document.createTable(1, 2);
            table.setWidth("100%");
            // Set column widths (each column 50%)
            CTTblLayoutType tblLayout = table.getCTTbl().getTblPr().addNewTblLayout();
            tblLayout.setType(STTblLayoutType.FIXED);
            setTableBorders(table);

            for (int col = 0; col < 2; col++) {
                CTTblGridCol tblCol = table.getCTTbl().addNewTblGrid().addNewGridCol();
                tblCol.setW(BigInteger.valueOf(5000)); // Adjust the width as necessary
            }

            //插入第一道题目
            Question question0 = setQuestionList.get(0);
            XWPFTableCell cell0 = table.getRow(0).getCell(0);
            cell0.setText("1." +question0.getQuestion());
            mergeCellsHorizontally(table,0,0,1);
            int rowNum = 1;
            rowNum = setInnerQuestion(question0, table, rowNum);
            table.createRow();
            rowNum++;
            int questionNum = 2;

            //插入后面的题目
            for (int i = 1; i < setQuestionList.size(); i++) {
                Question question = setQuestionList.get(i);
                XWPFTableRow row = table.createRow();
                rowNum++;
                row.getCell(0).setText(questionNum + "." + question.getQuestion());
                mergeCellsHorizontally(table,rowNum-1,0,1);
                questionNum++;
                rowNum = setInnerQuestion( question, table, rowNum);
                table.createRow();
                rowNum++;
            }

            //设置答案
            setAnswer(document,setQuestionList);
            //设置检查结果
            setCheckResult(document,setQuestionList);
            //Save the document
            FileOutputStream outputStream1 = new FileOutputStream(wordPath);
            document.write(outputStream1);
            outputStream1.close();
            document.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setCheckResult(XWPFDocument document, List<Question> setQuestionList) {
        document.createParagraph().createRun().setText(null);
        document.createParagraph().createRun().setText(null);
        String text =  "---------后面的为考题检查结果--------";
        document.createParagraph().createRun().setText(text);
        List<Subject> subjects = subjectMapper.getLeafsById(7L);
        List<Subject> leafsById = filterSubjects(engine,ata22Type,subjects);
        for (Subject subject : leafsById) {
            StringBuilder str = new StringBuilder();
            String name = subject.getName();
            Long id = subject.getId();
            Integer duration = subject.getDuration();
            Integer count = (int) Math.ceil((double) duration /60);
            //要在setQuestionList中找到count数量的题目
            str = new StringBuilder(name + "需要考" + count + "道题,");
            ArrayList<Question> questions = setQuestionList.stream().filter(question -> question.getSubjectId().equals(id)).collect(Collectors.toCollection(ArrayList::new));
            
            // 找到questions在setQuestionList中的索引
            List<Integer> questionIndices = new ArrayList<>();
            for (Question question : questions) {
                int index = setQuestionList.indexOf(question);
                if (index != -1) {
                    questionIndices.add(index);
                }
            }
            
            // 将索引添加到结果中
            str.append("实际题号: ");
            for (int i = 0; i < questionIndices.size(); i++) {
                str.append(questionIndices.get(i) + 1);
                if (i < questionIndices.size() - 1) {
                    str.append(", ");
                }
            }
            str.append(";").append("\n");
            document.createParagraph().createRun().setText(str.toString());
        }

        document.createParagraph().createRun().setText(null);
        document.createParagraph().createRun().setText(null);
        String text1 =  "---------后面的为关键知识点检查结果----------";

        document.createParagraph().createRun().setText(text1);
        document.createParagraph().createRun().setText(null);
        document.createParagraph().createRun().setText(null);


        //检查关键点是否都考到了
        List<SpecialCare> specialCares = specialCareMapper.selectList(new LambdaQueryWrapper<SpecialCare>().notLike(SpecialCare::getName,"KAP140"));
        for (SpecialCare specialCare : specialCares) {
            StringBuilder builder = new StringBuilder();
            Long subjectId = specialCare.getSubjectId();
            Integer id = specialCare.getId();
            String name = specialCare.getName();
            builder.append("关键点："+name+"，在本题目中第：");
            ArrayList<Question> questions = setQuestionList.stream().filter(question -> {
                return question.getSpecialCareId()!=null&&question.getSpecialCareId().equals(id) && question.getSubjectId().equals(subjectId);
            }).collect(Collectors.toCollection(ArrayList::new));
            if (questions.isEmpty()) {
                System.out.println("error");
            }

            // 找到questions在setQuestionList中的索引
            List<Integer> questionIndices = new ArrayList<>();
            for (Question question : questions) {
                int index = setQuestionList.indexOf(question);
                if (index != -1) {
                    questionIndices.add(index);
                }
            }

            if (questionIndices.size() != questions.size()) {
                System.out.println("error");
            }

            for (int i = 0; i < questionIndices.size(); i++) {
                builder.append((questionIndices.get(0) + 1));
                if (i<questionIndices.size()-1) {
                    builder.append("、");
                }
            }
            builder.append("道题中被考核到");

            builder.append(";");
            document.createParagraph().createRun().setText(builder.toString());
        }


    }

    /**
     * 设置答案
     * @param document
     * @param setQuestionList
     */
    private void setAnswer(XWPFDocument document, List<Question> setQuestionList) {
        document.createParagraph().createRun().setText("\n");

        String text =  "----------------------------------------------------------后面的为答案----------------------------------------------------------";
        document.createParagraph().createRun().setText(text);

        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < setQuestionList.size(); i++) {
            Question question = setQuestionList.get(i);
            String answer = question.getAnswer();
            builder.append(i+1+"."+answer+"   ");
        }
        document.createParagraph().createRun().setText(builder.toString());
    }

    private int setInnerQuestion( Question question, XWPFTable table, int rowNum) {
        //如果答案比较长，则答案表格变成4行
        if (question.getItem1().length()>12|| question.getItem2().length()>12|| question.getItem3().length()>12|| question.getItem4().length()>12
        ) {
            XWPFTableRow row1 = table.createRow();
            XWPFTableRow row2 = table.createRow();
            XWPFTableRow row3 = table.createRow();
            XWPFTableRow row4 = table.createRow();
            rowNum +=4;
            row1.getCell(0).setText("A."+ question.getItem1());
            row2.getCell(0).setText("B."+ question.getItem2());
            row3.getCell(0).setText("C."+ question.getItem3());
            row4.getCell(0).setText("D."+ question.getItem4());

            mergeCellsHorizontally(table, rowNum -1,0,1);
            mergeCellsHorizontally(table, rowNum -2,0,1);
            mergeCellsHorizontally(table, rowNum -3,0,1);
            mergeCellsHorizontally(table, rowNum -4,0,1);
        }
//                否则答案表格变成2行
        else {
            XWPFTableRow row1 = table.createRow();
            XWPFTableRow row2 = table.createRow();
            rowNum +=2;
            row1.getCell(0).setText("A."+ question.getItem1());
            row1.getCell(1).setText("B."+ question.getItem2());
            row2.getCell(0).setText("C."+ question.getItem3());
            row2.getCell(1).setText("D."+ question.getItem4());

        }
        return rowNum;
    }


    // 方法用于水平合并单元格
    public void mergeCellsHorizontally(XWPFTable table, int row, int fromCol, int toCol) {
        for (int colIndex = fromCol; colIndex <= toCol; colIndex++) {
            XWPFTableCell cell = table.getRow(row).getCell(colIndex);
            if ( colIndex == fromCol ) {
                // The first merged cell is set with RESTART merge value
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
            } else {
                // Cells which join (merge) the first one, are set with CONTINUE
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
            }
        }
    }
}
